<script setup lang="ts">
const model = defineModel<number>({
  required: true
})
const content = ref<string>(model.value!.toString())

const inputRef = ref()

const props = withDefaults(
  defineProps<{
    step: number
    type?: 'number' | 'angle'
  }>(),
  {
    step: 0.1,
    type: 'number'
  }
)

const suffix = ref(props.type === 'angle' ? '°' : '')


watch(model, (value) => {
  formatContent(value)
})

/**
 * 获取去掉后缀的值
 */
const getNumberValue = () => {
  let num = content.value
  if (suffix.value) {
    const suffixIndex = num.indexOf(suffix.value)
    if (suffixIndex > -1) {
      num = num.slice(0, suffixIndex)
    }
  }

  return num
}

/**
 * 格式化
 */
const formatNum = (newNum?: number) => {
  if (newNum && props.type === 'angle') {
    newNum = newNum! * 180 / Math.PI
  }
  let num = newNum || getNumberValue()

  if (num === '' || isNaN(Number(num))) {
    num = '0'
  }

  num = Number(num).toFixed(3)

  return num
}
const formatValue = (newNum?: number) => {
  formatContent(newNum)

  let num = Number(formatNum(newNum))
  if (props.type === 'angle') {
    num = (num * Math.PI) / 180
  }
  model.value = num
}
const formatContent = (newNum?: number) => {
  content.value = formatNum(newNum) + suffix.value
}

/**
 * 失焦时格式化值
 */
const handleFoucusout = () => {
  formatValue()
}

/**
 * 回车触发失焦
 */
const handleKeydownEnter = () => {
  inputRef.value.blur()
}

/**
 * 处理拖动
 */
const handleMousedown = (event: MouseEvent) => {
  event.preventDefault()

  const initialY = event.clientY
  // const initialValue = props.type === 'angle' ? model.value! * 180 / Math.PI : model.value!
  const initialValue = model.value!
  const sensitivity = 1 // 灵敏度系数，每1像素对应一个step变化

  const handleMousemove = (event: MouseEvent) => {
    event.preventDefault()

    const currentY = event.clientY
    const deltaY = initialY - currentY // 向上移动为正
    let change = (deltaY / sensitivity) * props.step
    if (props.type === 'angle') {
      change = change / 180 * Math.PI
    }
    const newValue = initialValue + change

    formatValue(newValue)
  }

  const handleMouseup = () => {
    document.removeEventListener('mousemove', handleMousemove)
    document.removeEventListener('mouseup', handleMouseup)
  }

  document.addEventListener('mousemove', handleMousemove)
  document.addEventListener('mouseup', handleMouseup)
}

/**
 * 点击聚焦
 */
const handleClick = () => {
  inputRef.value.select()
}

onMounted(() => {
  formatContent(model.value)
})
</script>

<template>
  <input
    ref="inputRef"
    class="mouse-scroll-input"
    v-model="content"
    @focusout="handleFoucusout"
    @keydown.enter="handleKeydownEnter"
    @mousedown="handleMousedown"
    @click="handleClick"
  />
</template>

<style scoped lang="scss">
.mouse-scroll-input {
  border: 0;
  font-size: 16px;
  width: 80px;
  color: #2d8cf0;
  margin: 0 8px;
  padding: 4px;
  cursor: ns-resize;

  &:focus {
    outline: none;
    background-color: rgb(220, 220, 220);
  }
}
</style>
